/**
 * 
 */
package com.estock.web.controller;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.estock.common.model.security.Stock;
import com.estock.common.model.security.StockCategory;
import com.estock.common.util.StockUtil;
import com.estock.common.util.support.ESLogger;
import com.estock.platform.http.SinaStockBulkConn;
import com.estock.platform.http.response.SinaStockBulkResponse;
import com.estock.web.service.StockCategoryService;
import com.estock.web.service.StockService;

/**
 * @author richard
 * 
 */
@Controller
public class StockController {

	protected final ESLogger logger = ESLogger.getLogger(StockController.class);
	
	@Resource
	StockService stockService; 
	public StockService getStockService() {
		return stockService;
	}
	
	@Resource
	StockCategoryService stockCategoryService; 
	public StockCategoryService getStockCategoryService() {
		return stockCategoryService;
	}
	
	//////// Return View

	//////// Return Json
	@RequestMapping(value="getStockNumByType.es", method = RequestMethod.GET)
	@ResponseBody
	public int getStockNumByType(@RequestParam int type) throws Exception {
		logger.info("request url: /getTotalNumOfStock.es");
		return getStockService().getStockNumByType(type);
	}
	
	@RequestMapping(value="stocklist_json.es", method = RequestMethod.GET)
	@ResponseBody
	public List<Stock> getAllStocksByType(@RequestParam int type, 
			@RequestParam int currentPage, @RequestParam int itemsPerPage) throws Exception {
		logger.info("request url: /stocklist_json.es with parameter type = " + type);
		return getStockService().findAllStocksByType(type, currentPage, itemsPerPage);
	}
	

	@RequestMapping(value="findStocksByCategory_json.es", method = RequestMethod.GET)
	@ResponseBody
	public List<Stock> findStocksByCategoryId(@RequestParam int stockCategoryId) {
		return getStockService().findStocksByCategoryId(stockCategoryId);
	}
	
	@RequestMapping(value="stock/{code}_json.es", method = RequestMethod.GET)
	@ResponseBody
	public Stock saveOrUpdateStockbyCode(@PathVariable String code) throws Exception {
		logger.info("receive stock with code %s and request url /stock/%s_json.es", code, code);
		Stock stock = getStockService().findStockByCode(code);
		if (stock == null) {
			try {
				List<Stock> stocks = new ArrayList<Stock>(1);
				stocks.add(new Stock(code, "", StockUtil.getStockTypeByCode(code)));
				SinaStockBulkResponse response = 
						(SinaStockBulkResponse) new SinaStockBulkConn().request(stocks, false);
				
				List<Stock> responseStocks = response.getStocks();
				if (responseStocks == null || responseStocks.isEmpty()) {
					throw new RuntimeException("Cannot get stock information from sina!");
				}
				getStockService().saveOrUpdate(stock);
				//CacheManager.getInstance().refreshWithStock(stock);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		
		return stock;
	}
	
	@RequestMapping(value="saveStockToCategory.es", method = RequestMethod.GET)
	@ResponseBody
	public Stock saveStockToCategory(@RequestParam String code, @RequestParam Long stockCategoryId) throws Exception {
		Stock stock = saveOrUpdateStockbyCode(code);
		StockCategory stockCategory = getStockCategoryService().findById(stockCategoryId);
		
		if (!stockCategory.getStocks().contains(stock)) {
			stockCategory.addStock(stock);
			getStockCategoryService().saveOrUpdate(stockCategory);
		}
		
		return stock;
	}
	
	@RequestMapping(value="deleteStockById.es", method = RequestMethod.GET)
	@ResponseBody
	public String deleteStockById(@RequestParam Long stockId) throws Exception {
		logger.info("start deleting stock with id: %s", stockId);
		getStockService().deleteStockById(stockId);
		return "success";
	}
	
	
	////////Self-Select stock related
	
	@RequestMapping(value="getSelfSelectNum.es", method = RequestMethod.GET)
	@ResponseBody
	public int getSelfSelectNum() throws Exception {
		logger.info("request url: /getSelfSelectNum.es");
		return getStockService().getSelfSelectNum();
	}
	
	@RequestMapping(value="findAllSelfSelects.es", method = RequestMethod.GET)
	@ResponseBody
	public List<Stock> findAllSelfSelects(@RequestParam int currentPage, 
			@RequestParam int itemsPerPage) throws Exception {
		logger.info("request url: /findAllSelfSelects.es");
		return getStockService().findAllSelfSelects(currentPage, itemsPerPage);
	}
	
	@RequestMapping(value="saveSelfSelectByCode.es", method = RequestMethod.GET)
	@ResponseBody
	public Stock saveSelfSelectByCode(@RequestParam String code) throws Exception {
		logger.info("request url: /saveSelfSelectByCode.es with code=" + code);

		Stock selfSelect = getStockService().findSelfSelectByCode(code);
		if (selfSelect != null) {
			return selfSelect;
		} else {
			Stock stock = getStockService().findStockByCode(code);
			if (stock == null) {
				try {
					List<Stock> stocks = new ArrayList<Stock>(1);
					stocks.add(new Stock(code, "", StockUtil.getStockTypeByCode(code)));
					SinaStockBulkResponse response = 
							(SinaStockBulkResponse) new SinaStockBulkConn().request(stocks, false);
					
					List<Stock> responseStocks = response.getStocks();
					if (responseStocks == null || responseStocks.isEmpty()) {
						throw new RuntimeException("Cannot get stock information from sina!");
					}
					stock = responseStocks.get(0);
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			}
			
			stock.setIsSelfSelect(true);
			getStockService().saveOrUpdate(stock);
			//CacheManager.getInstance().refreshWithStock(stock);
			return stock;
		}
	
	}
	
	/**
	 * 
	 * Get current prices for all selfSelects.<br>
	 * 
	 * @param selfSelects
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="getCurrentPrices.es", method = RequestMethod.POST)
	@ResponseBody
	public List<String> getCurrentPrices(@RequestBody List<Stock> selfSelects) throws Exception {
		SinaStockBulkResponse response = 
				(SinaStockBulkResponse) new SinaStockBulkConn().request(selfSelects, false);
		
		List<Stock> responseStocks = response.getStocks();
		List<String> currentPrices = new ArrayList<String>(); 
		for (Stock stock : responseStocks) {
			getStockService().updateLatestPrice(stock.getCode(), stock.getLatestPrice());
			currentPrices.add(String.valueOf(stock.getLatestPrice()));
		}
		
		return currentPrices;
	}
	
	@RequestMapping(value="deleteSelfSelectById.es", method = RequestMethod.GET)
	@ResponseBody
	public String deleteSelfSelectById(@RequestParam Long stockId) throws Exception {
		logger.info("start deleting selfSelect with id: %s", stockId);
		getStockService().deleteSelfSelectById(stockId);
		return "success";
	}
	
}
